﻿namespace NET7.Api.Controllers;

/// <summary>
/// 鉴权相关
/// </summary>
// [Route("auth")]
[Route("api/[controller]/[action]")]
public class AuthController : BaseController
{
    private readonly IConfiguration _config;

    public AuthController(IConfiguration config)
    {
        _config = config;
    }

    /// <summary>
    /// 一般测试
    /// </summary>
    /// <returns></returns>
  [HttpGet]
    public IActionResult Index()
    {
        return Ok("hello world");
    }
    
    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="dto">测试帐号: username="admin",password="123456"</param>
    /// <returns></returns>
    [AllowAnonymous]
    [HttpPost("login")]
    [ProducesResponseType(typeof(TokenModel), StatusCodes.Status200OK)]
    public Task<IActionResult> Login(LoginDto dto)
    {
        // 模拟登录
        var check = dto.UserName == "admin" && dto.Password == "123456";
        if (!check) return Task.FromResult(JsonView("帐号错误"));
        var user = new LoginModel { Id = 10002, Name = "张三", Avatar = "http://demo.com/a.png" };

        // 「系统推荐」与「自定义」的Claims
        var claims = new[]
        {
            new Claim(MyClaims.UserId, user.Id.ToString()),
            new Claim(MyClaims.UserName, user.Name),
            new Claim(MyClaims.Department, "技术部"),
            new Claim(MyClaims.Group, dto.Group),
            new Claim(ClaimTypes.Role, dto.Role),
            // new Claim(JwtRegisteredClaimNames.Jti, "admin")
        };

        var model = GenJwtToken(claims);
        MemoryCacheHelper.Set($"{Global.JwtToken}_{user.Id}", model.RefreshToken, TimeSpan.FromDays(30));
        return Task.FromResult<IActionResult>(Ok(model));
    }

    /// <summary>
    /// 刷新访问令牌
    /// </summary>
    /// <param name="refreshToken"></param>
    /// <returns></returns>
    // [AllowAnonymous]   从头部获取
    [HttpGet("refresh")]
    [ProducesResponseType(typeof(LoginModel), StatusCodes.Status200OK)]
    public Task<IActionResult> Refresh(string refreshToken)
    {
        var userId = User.FindFirst(MyClaims.UserId)?.Value;
        var userName = User.FindFirst(MyClaims.UserName)?.Value;
        var department = User.FindFirst(MyClaims.Department)?.Value;
        // var department = User.Claims.FirstOrDefault(x=>x.Type=="department")?.Value;

        var old = MemoryCacheHelper.Get<string>($"{Global.JwtToken}_{userId}");
        if (old == null || old != refreshToken) return Task.FromResult(JsonView("刷新令牌失败"));


        var claims = new[]
        {
            new Claim(MyClaims.UserId, userId!),
            new Claim(MyClaims.UserName, userName!),
            new Claim(MyClaims.Department, department!)
        };

        var model = GenJwtToken(claims);
        MemoryCacheHelper.Set($"{Global.JwtToken}_{userId}", model.RefreshToken, TimeSpan.FromDays(30));
        return Task.FromResult<IActionResult>(Ok(model));
    }

    
    /// <summary>
    /// 基于角色的授权 - 仅允许管理员和经理访问
    /// </summary>
    /// <returns></returns>
   [HttpGet]
    [Authorize(Roles = "admin,manager")]
    public IActionResult ManagerRole()
    {
        return Ok("hello");
    }

    /// <summary>
    /// 策略角色 - 仅vip和内部员工(staff)角色可访问
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Authorize(Policy = "RoleGroup")]
    public IActionResult RoleGroup()
    {
        return Ok("hello");
    }

    /// <summary>
    /// 策略分组 - 仅1001、1002管理员组可以访问
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Authorize(Policy = "ManagerGroup")]
    public IActionResult ManagerGroup()
    {
        return Ok("hello");
    }
    
    /// <summary>
    /// 生成JWT令牌
    /// </summary>
    /// <param name="claims"></param>
    /// <returns></returns>
    private TokenModel GenJwtToken(IEnumerable<Claim> claims)
    {
        var model = new TokenModel
        {
            Expires = DateTime.Now.AddDays(7),
            RefreshToken = Guid.NewGuid().ToString("N"),
        };

        //授权与签名信息
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"]!));
        var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var token = new JwtSecurityToken(
            issuer: _config["Jwt:Issuer"],
            audience: _config["Jwt:Audience"],
            claims: claims,
            expires: model.Expires,
            signingCredentials: cred);

        model.AccessToken = new JwtSecurityTokenHandler().WriteToken(token);
        return model;
    }
}


